package com.m4f.city.business.oauth2.impl;

import java.util.ArrayList;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;

import com.m4f.city.business.domain.Application;
import com.m4f.city.business.domain.InternalUser;
import com.m4f.city.business.service.ifc.ApplicationService;
import com.m4f.city.constant.ApiErrorCodes;
import com.m4f.city.exception.M4FApiException;

public class DataStoreClientDetails implements ClientDetailsService {
	
	private ApplicationService appService;
	
	public DataStoreClientDetails() {
		super();
	}

	@Override
	public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception {
		try {
			Authentication authenticationContext = SecurityContextHolder.getContext().getAuthentication();
			Application app = this.appService.getAppliaction(clientId);
			//TODO some possible values are password,authorization_code,refresh_token
			ArrayList<String> grantTypes = new ArrayList<String>();
			grantTypes.add("authorization_code");
			grantTypes.add("password");
			grantTypes.add("refresh_token");
			
			if(app == null) {
				throw new InvalidClientException("Client not found: " + clientId);
				//throw new M4FApiException(ApiErrorCodes.CLIENT_INVALID_COD, ApiErrorCodes.CLIENT_INVALID_MSG, ApiErrorCodes.CLIENT_INVALID_DSC);
			} else {
				// INFO: Here we have to try to check if the user has this application. If not throw an Exception.
				if(authenticationContext.getPrincipal() instanceof InternalUser) {
					InternalUser user = (InternalUser) authenticationContext.getPrincipal();
					if(user.getApplicationIds() != null && user.getApplicationIds().contains(app.getId())) {
						app.setAuthorizedGrantTypes(grantTypes);
					} else {
						throw new InvalidClientException("The user has not acces to the application with name: " + app.getName());
						//throw new M4FApiException(ApiErrorCodes.CLIENT_INVALID_COD, ApiErrorCodes.CLIENT_INVALID_MSG, ApiErrorCodes.CLIENT_INVALID_DSC);
					}
				} else {
					app.setAuthorizedGrantTypes(grantTypes);
				}
			}
			
			return app;
		} catch(Exception e) {
			e.printStackTrace(); // TODO
			throw new OAuth2Exception(e.getMessage()); // TODO not return null!
		}
	}

	public void setAppService(ApplicationService appService) {
		this.appService = appService;
	}
	
}
